Skip to content

feat: access protection — AllowedCallers, ChainProtected, mode verify#1

Merged
OpsKern merged 1 commit into
mainfrom
pr/access-protection
May 6, 2026
Merged

feat: access protection — AllowedCallers, ChainProtected, mode verify#1
OpsKern merged 1 commit into
mainfrom
pr/access-protection

Conversation

@OpsKern
Copy link
Copy Markdown
Contributor

@OpsKern OpsKern commented May 5, 2026

Summary

Closes the tamper-evident partial EU AI Act Article 12 requirement by adding filesystem and application-level access controls to the Merkle chain.

  • Config.AllowedCallers []string — when non-empty, writ.New rejects any CallerID not in the list. Nil/empty = allow all (backwards-compatible).
  • Client.ChainProtected() bool — attempts to set FS_APPEND_FL (equivalent to chattr +a) on the chain file via ioctl on Linux. Returns false on unsupported filesystems or non-Linux platforms. Operators who lack the privilege to set the kernel flag can still enforce it via chattr +a manually; ChainProtected() checks the current state.
  • newJSONLStore mode verify — after creating or opening the chain file, stats the permissions and auto-chmods to 0o600 if they drifted (umask, manual changes).
  • policies/default/caller_allowlist.rego — example Rego policy for operators who want to enforce the allowlist at the OPA layer instead of (or in addition to) the Go-level check.

Compliance impact

Before After
Tamper-evident: PARTIAL Tamper-evident: MET

chattr +a via ChainProtected() + AllowedCallers closes the "write access controls not yet specified" gap from the v0.1.0 compliance table.

Test plan

  • TestAllowedCallersPermitsKnownCaller
  • TestAllowedCallersDeniesUnknownCaller
  • TestAllowedCallersNilPermitsAnyCaller
  • TestChainProtectedReturnsBool
  • go test -race ./... green on Linux (bazzite) and macOS
  • gosec ./... — 0 issues, 5 nosec suppressions (G103/G304 for ioctl)

🤖 Generated with Claude Code

- Config.AllowedCallers []string: when non-empty, writ.New rejects any
  CallerID not in the list (backwards-compat: nil/empty allows all)
- Client.ChainProtected() bool: attempts to set FS_APPEND_FL (chattr +a)
  via ioctl on Linux; always false on other platforms
- newJSONLStore: verifies chain file is 0600 on open; auto-chmod if drifted
- protect_linux.go / protect_other.go: OS-gated ioctl implementation
- policies/default/caller_allowlist.rego: example policy for Rego-level
  caller filtering (commented-out; operators activate as needed)
- Tests: AllowedCallers permit/deny/nil cases, ChainProtected smoke

Closes partial EU AI Act Article 12 requirement: tamper-evident (access protection).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@OpsKern OpsKern force-pushed the pr/access-protection branch from 79a2fd9 to 1526183 Compare May 6, 2026 02:08
@OpsKern OpsKern merged commit 54adbcd into main May 6, 2026
1 check passed
@OpsKern OpsKern deleted the pr/access-protection branch May 6, 2026 02:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant